﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Factories;
using FarseerPhysics.Common;
using FarseerPhysics.Collision.Shapes;
using FarseerPhysics.Controllers;

namespace BHG.System
{
    class PhysicsEngine
    {
        #region Fields
        public World gameWorld { get; set; }
        protected static PhysicsEngine _instance;
        #endregion

        public static PhysicsEngine Instance {
            get { if ( _instance == null ) createNewInstance(); return _instance; }
            internal set { _instance = value; }
        }
        public Vector2 Gravity {
            get { return Instance.gameWorld.Gravity; }
            set { Instance.gameWorld.Gravity = value; }
        }

        #region Initialization
        /// <summary>
        /// Creates new Physics engine with zero gravity 
        /// </summary>
        protected PhysicsEngine() {
            gameWorld = new World(Vector2.Zero);
        }

        protected static void createNewInstance() {
            _instance = new PhysicsEngine();
        }
        #endregion

        #region Public methods

        public void Reset() {
            createNewInstance();
        }

        /// <summary>
        /// Removes object from engine
        /// </summary>
        /// <param name="obj">Game object to remove</param>
        public void removeObjectFromPhysics( GameObject obj ) {
            Instance.gameWorld.RemoveBody(obj.body);
        }

        /// <summary>
        /// Create black hole from point
        /// </summary>
        /// <param name="point"></param>
        /// <param name="gType"></param>
        /// <param name="strenght"></param>
        /// <returns></returns>
        public GravityController AddGravityCenter( Vector2 point, GravityType gType, float strenght ) {
            GravityController GC = new GravityController(strenght);
            GC.AddPoint(point);
            GC.GravityType = gType;
            Instance.gameWorld.AddController(GC);

            return GC;
        }

        /// <summary>
        /// create black hole from game objet
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="gType"></param>
        /// <param name="strenght"></param>
        /// <returns></returns>
        public GravityController AddGravityCenter( GameObject obj, GravityType gType, float strenght ) {
            GravityController GC = new GravityController(strenght);
            GC.AddBody(obj.body);
            GC.GravityType = gType;
            Instance.gameWorld.AddController(GC);

            return GC;
        }

        public void Update( float time ) {
            Instance.gameWorld.Step(time);
        }
        #endregion
    }
}
